package com.dsg.support;

import com.dsg.common.util.toolbox.CollectionUtil;
import com.dsg.common.util.toolbox.StringUtil;
import com.dsg.entity.system.DsgSysParameter;
import com.dsg.service.system.IDsgSysParameterService;
import com.powerbridge.core.util.FileUtil;
import org.iq80.leveldb.DB;
import org.iq80.leveldb.DBFactory;
import org.iq80.leveldb.Options;
import org.iq80.leveldb.WriteOptions;
import org.iq80.leveldb.impl.Iq80DBFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.Charset;
import java.util.List;

/**
 * 缓存
 *
 * @author yuanfengzhong
 */
@Component
public final class LeveldbAccess implements InitializingBean {
    private static final Charset CHARSET = Charset.forName("utf-8");

    static Options options = new Options().createIfMissing(true);
    static DBFactory factory = Iq80DBFactory.factory;

    DB db;

    @Autowired
    private IDsgSysParameterService dsgSysParameterService;

    private String leveldbPath="/levelTemp";

    public LeveldbAccess() {
    }

    public void setSysLeveldbPath() {
        List<DsgSysParameter> parameter = dsgSysParameterService.selectByList("LEVEL_DB_PATH");
        if (CollectionUtil.isNotEmpty(parameter)) {
            setLeveldbPath(parameter.get(0).getParaValue());
        }
    }

    @Override
    public void afterPropertiesSet() {
        String cachePath = getLeveldbPath();
        FileUtil.deleteDirectory(cachePath);
    }

    public void open() throws Exception {
        if (StringUtil.isEmpty(getLeveldbPath())) {
            setSysLeveldbPath();
        }
        String cachePath = getLeveldbPath();
        File file = new File(cachePath);
        try {
            if (db == null) {
                db = factory.open(file, options);
            }
        } catch (IOException e) {
            throw e;
        }
    }

    public void close() {
        if (db != null) {
            try {
                db.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                db = null;
            }
        }
    }

    /**
     * 存
     *
     * @param key
     * @param value
     */
    public <T> void put(String key, T value) {
        if (key == null) {
            return;
        }
        if (value == null) {
            return;
        }
        try {
            if (db == null) {
                open();
            }
            WriteOptions writeOptions = new WriteOptions();
            writeOptions.snapshot(true);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(value);
            db.put(key.getBytes(CHARSET), baos.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 取
     *
     * @param key
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String key) {
        if (key == null) {
            return null;
        }
        try {
            if (db == null) {
                open();
            }
            byte[] valueByte = db.get(key.getBytes(CHARSET));
            if (valueByte == null) {
                return null;
            }
            ByteArrayInputStream bais = new ByteArrayInputStream(valueByte);
            ObjectInputStream ois = new ObjectInputStream(bais);
            return (T) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除缓存数据
     *
     * @param key
     */
    public void delete(String key) {
        db.delete(key.getBytes(CHARSET));
    }

    public String getLeveldbPath() {
        return leveldbPath;
    }

    public void setLeveldbPath(String leveldbPath) {
        this.leveldbPath = leveldbPath;
    }

    public String genCacheKey(Object... args) {
        String result = "";
        for (int i = 0; i < args.length; i++) {
            if (StringUtil.isEmpty(result)) {
                result += args[i];
            } else {
                result += "-" + args[i];
            }
        }
        return result;
    }
}
